﻿using CommonDevelop;
using CommonDevelop.Cache;
using CommonDevelop.DB;
using ManageDB;
using ManageDto;
using ManageRepository;
using System;
using System.Collections.Generic;
using System.IO;

namespace ManageService
{
    /// <summary>
    /// 附件服务层接口
    /// </summary>
    public interface IEncService : IBaseService<Base_Enc>
    {
        string SaveAnnexes(string folderId, string fileGuid, string fileName, string fileRelative, int chunks);
        long SaveAnnexesToFile(string fileGuid, string filePath, int chunks);
        void SaveChunkAnnexes(string fileGuid, int chunk, Stream fileStream);
        void RemoveChunkAnnexes(string fileGuid, int chunks);

        bool RemoveEnc(string keyword);
        List<EncDto> GetEncList(string EncObjectId);
        EncDto GetEnc(string EncId);
    }

    /// <summary>
    /// 附件服务层
    /// </summary>
    public class EncService : BaseService<Base_Enc, IEncRepository>, IEncService
    {
        private string cacheKey = "Common_Enc_";
        private readonly IPathProvider pathProvider;
        /// <summary>
        /// 构造注入
        /// </summary>
        public EncService(IPathProvider pathProvider, IEncRepository repository) : base(repository)
        {
            this.pathProvider = pathProvider;
        }

        #region---文件操作---

        /// <summary>
        /// 保存附件（支持大文件分片传输）
        /// </summary>
        public string SaveAnnexes(string folderId, string fileGuid, string fileName, string fileRelative, int chunks)
        {
            try
            {
                //获取文件完整文件名(包含绝对路径)
                string filePath = this.pathProvider.MapPath("Enc");
                string uploadDate = DateTime.Now.ToString("yyyyMMdd");
                string FileEextension = Path.GetExtension(fileName);
                string virtualPath = $"{filePath}\\{folderId}\\{uploadDate}\\{fileGuid}{FileEextension}";
                string RelativePath = $"{fileRelative}\\{folderId}\\{uploadDate}\\{fileGuid}{FileEextension}";
                //创建文件夹
                string path = Path.GetDirectoryName(virtualPath);
                Directory.CreateDirectory(path);

                if (!File.Exists(virtualPath))
                {
                    long filesize = SaveAnnexesToFile(fileGuid, virtualPath, chunks);
                    if (filesize == -1)// 表示保存失败
                    {
                        RemoveChunkAnnexes(fileGuid, chunks);
                        return "";
                    }

                    EncDto EncEntity = new EncDto();
                    EncEntity.EncObjectId = folderId;
                    EncEntity.EncFileID = fileGuid;
                    EncEntity.EncName = fileName;
                    EncEntity.EncEx = FileEextension;
                    EncEntity.EncUrl = RelativePath;
                    EncEntity.EncAddress = virtualPath;
                    EncEntity.EncType = FileEextension.Replace(".", "");
                    EncEntity.FileSize = filesize.ToString();

                    this.Add<EncDto>(EncEntity);
                    return EncEntity.EncId;
                }
                return "";
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 保存附件到文件中
        /// </summary>
        /// <param name="fileGuid">文件主键</param>
        /// <param name="filePath">文件路径</param>
        /// <param name="chunks">总共分片数</param>
        /// <param name="buffer">文件二进制流</param>
        /// <returns>-1:表示保存失败</returns>
        public long SaveAnnexesToFile(string fileGuid, string filePath, int chunks)
        {
            try
            {
                long filesize = 0;
                //创建一个FileInfo对象
                FileInfo file = new FileInfo(filePath);
                //创建文件
                FileStream fs = file.Create();
                for (int i = 0; i < chunks; i++)
                {
                    byte[] bufferByRedis = SystemCache.Read<byte[]>(cacheKey + i + "_" + fileGuid);
                    if (bufferByRedis == null)
                    {
                        return -1;
                    }
                    //写入二进制流
                    fs.Write(bufferByRedis, 0, bufferByRedis.Length);
                    filesize += bufferByRedis.Length;
                    SystemCache.RemoveCache(cacheKey + i + "_" + fileGuid);
                }
                //关闭文件流
                fs.Close();
                return filesize;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 保存分片附件
        /// </summary>
        /// <param name="fileGuid">文件主键</param>
        /// <param name="chunk">分片文件序号</param>
        /// <param name="fileStream">文件流</param>
        public void SaveChunkAnnexes(string fileGuid, int chunk, Stream fileStream)
        {
            try
            {
                byte[] bytes = new byte[fileStream.Length];
                fileStream.Read(bytes, 0, bytes.Length);
                SystemCache.Write<byte[]>(cacheKey + chunk + "_" + fileGuid, bytes);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 移除文件分片数据
        /// </summary>
        /// <param name="fileGuid">文件主键</param>
        /// <param name="chunks">文件分片数</param>
        public void RemoveChunkAnnexes(string fileGuid, int chunks)
        {
            try
            {
                for (int i = 0; i < chunks; i++)
                {
                    SystemCache.RemoveCache(cacheKey + i + "_" + fileGuid);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        #endregion

        public bool RemoveEnc(string keyword)
        {
            this.Delete(keyword);
            return true;
        }

        public List<EncDto> GetEncList(string EncObjectId)
        {
            List<EncDto> result = new List<EncDto>();
            if (string.IsNullOrWhiteSpace(EncObjectId))
                return result;

            var data = this.repository_DB.GetList(a => a.EncObjectId == EncObjectId);
            result = data.MapToList<Base_Enc, EncDto>();
            return result;
        }

        public EncDto GetEnc(string EncId)
        {
            if (string.IsNullOrWhiteSpace(EncId))
                return null;

            EncDto result = this.Get<EncDto>(EncId).Outcome();
            return result;
        }
    }
}
